{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Clojupyter demo: Jupyter Notebook-only features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook demonstrates some features of Clojupyter for Jupyter Notebook. Please note that it uses <font color=red>**Notebook-only functionality**</font> and does not render correctly using *Jupyter Lab* which uses renderers instead of allowing direct access to external Javascript libraries.  See the Jupyter Lab demo notebook for details.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Charting using  external Javascript library: Highcharts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since you can render arbitrary HTML using display/hiccup-html, it's pretty easy to use external Javascript libraries to do things like generate charts. Here's an example using Highcharts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(require '[clojupyter.javascript.alpha :as cjp-js])\n",
    "(require '[clojupyter.display :as display])\n",
    "(require '[clojupyter.misc.helper :as helper])\n",
    "(require '[clojure.data.json :as json])\n",
    "(cjp-js/amd-add-javascript-html\n",
    "  [{:ident :hicharts :exports \"Highcharts\" :url \"https://code.highcharts.com/highcharts\"}])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(def raw-data (map #(int (+ (* 22 (+ % (Math/random)) 78))) (range)))\n",
    "(def data-1 (take 25 raw-data))\n",
    "(def data-2 (take 25 (drop 25 raw-data)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(defn highchart-chart\n",
    "  [nodeid data]\n",
    "  (cjp-js/amd-wrap-require [:hicharts]\n",
    "    (format \"function(hc){hc.chart('%s',%s)}\" nodeid (json/write-str data))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(def CHART {:chart {:type \"line\"}\n",
    "            :title {:text (str \"External js library: Highcharts plot using \" (:formatted-version clojupyter/*version*))}\n",
    "            :series [{:data data-1} {:data data-2}]})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(display/hiccup-html \n",
    " (let [nodeid (gensym)]\n",
    "   [:div \n",
    "    [:div {:id nodeid}]\n",
    "    [:script (highchart-chart nodeid CHART)]]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=red>**OBS The cell above fails to render the resulting Vega graph.  Needs fixing.**</font>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Charting using Clojure visualization library Oz"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Oz](https://github.com/metasoarous/oz) is a data visualization and scientific document processing library for Clojure built around [Vega Lite](https://vega.github.io/vega-lite/) & [Vega](https://vega.github.io/).  Oz provides has a built-in interface to clojupyter, so all we have to do to use it is to load it into Clojure:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(helper/add-dependencies '[metasoarous/oz \"1.5.6\"])\n",
    "(require '[oz.notebook.clojupyter :as oz]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For this demo we define some simple functions generating some data compatible with the high-level  charting library:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(defn datapt [[s n]] {:Index s, :Value n})\n",
    "(defn graph  [vs]    {:data {:values vs}, \n",
    "                      :mark :line\n",
    "                      :encoding {:x {:field :Index}\n",
    "                                 :y {:field :Value}}})\n",
    "(def graph-it (comp graph (partial map datapt) (partial apply map vector)));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With a generator for (slightly) random data..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(defn raw-data [] (map #(+ % (rand-int 25)) (range)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "...we can create a graph using Vega Lite:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(->> [(range) (take 150 (raw-data))]\n",
    "     graph-it\n",
    "     oz/view!)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: The above cell is *not* supposed to render correctly in Jupyter Lab, <font color=red>**only Jupyter Notebook**</font>.  See Jupyter Lab demo notebook for details on how accomplish the same thing in Jupyter Lab."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Clojure (clojupyter-v0.2.2-SNAPSHOT@2bad)",
   "language": "clojure",
   "name": "clojupyter"
  },
  "language_info": {
   "file_extension": ".clj",
   "mimetype": "text/x-clojure",
   "name": "clojure",
   "version": "1.10.0"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": false,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": false,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
